package com.iwomy.secureplat.common.log.aspect;

import com.iwomy.secureplat.common.log.annotation.ReckonTime;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
 
@Slf4j  //记录日志
@Component  //将当前类交给ioc容器管理，成为ioc容器中的bean对象
@Aspect //代表当前类是一个aop类，在该类中定义模板方法来面向特定方法编程
public class ReckonTimeAspect {
 
    /**
     * Spring AOP：统计各个业务层方法执行耗时
     *
     * @param joinPoint 封装原始方法的所有信息
     * @return Object 原始方法的返回值
     * @throws Throwable 运行原始方法可能出现异常，向上抛出
     */
	@Around("@annotation(reckonTime)")//切入点表达式
    public Object recordTime(ProceedingJoinPoint joinPoint, ReckonTime reckonTime) throws Throwable {
        //1. 记录开始时间
        long begin = System.currentTimeMillis();    //拿到当前系统毫秒值，因为毫秒值数值较大，所以考虑用long存储
 
        //2. 调用原始方法运行
        Object result = joinPoint.proceed();    //原始方法运行可能会有返回值，将其交给Object对象（祖宗类）
 
        //3. 记录结束时间, 计算方法执行耗时
        long end = System.currentTimeMillis();  //拿到当前系统毫秒值
        //在日志中输出调用的具体方法的运行耗时
        log.info(joinPoint.getSignature()+"方法执行耗时: {}ms", end-begin);
 
        return result;
    }
 
    /**
     * 1.@Around注解
     *   （1）指定该方法作用在哪些方法上
     *   （2）切入点表达式：指定作用的具体方法
     *   （3）"execution(* com.service.impl.UserServiceImpl.*(..))"
     *          运行这个包下的所有的接口或者类中所有的方法时都会运行recordTime()方法中封装的公用的逻辑代码
     * 2.ProceedingJoinPoint：AOP中提供的一个api
     * 3.proceed()方法：调用原始方法
     * 4.getSignature()：拿到原始方法的签名，
     */
 
}